package me.firstapp.repository.weixin.member.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Repository;

import me.firstapp.common.utils.DateUtils;
import me.firstapp.common.utils.Page;
import me.firstapp.common.utils.StrUtils;
import me.firstapp.module.weixin.member.Member;
import me.firstapp.repository.base.impl.EntityRepositoryImpl;
import me.firstapp.repository.weixin.member.MemberRepository;

@Repository
public class MemberRepositoryImpl extends EntityRepositoryImpl<Member> implements MemberRepository {

	@Override
	protected Class<Member> getPersistentClass() {
		return Member.class;
	}

	@Override
	public Member findMemberByOpenId(String openId) {
		StringBuilder sql = new StringBuilder("FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.openId = :openId ");
		parameters.put("openId", openId);

		List<Member> result = super.query(Member.class, sql.toString(), parameters);
		return result.isEmpty() ? null : result.get(0);
	}

	@Override
	public Long findTotalFansCounts(String chiefOpenId) {
		StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.chiefOpenId = :chiefOpenId ");
		parameters.put("chiefOpenId", chiefOpenId);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		List<Long> result = super.query(Long.class, sql.toString(), parameters);
		return result.isEmpty() ? 0L : result.get(0);
	}

	@Override
	public List<Member> findFansPage(Integer pageNo, Integer pageSize, String chiefOpenId) {
		StringBuilder sql = new StringBuilder("FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.chiefOpenId = :chiefOpenId ");
		parameters.put("chiefOpenId", chiefOpenId);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		sql.append(" ORDER BY bean.registerTime DESC ");

		List<Member> result = queryForPageList(Member.class, sql.toString(), parameters, pageNo, pageSize);

		return result;
	}

	@Override
	public Page<Member> findMemberPage(Integer pageNo, Integer pageSize, Map<String, Object> searchParams,
			String sortParam, String sortType, Date startTime, Date endTime, Integer vipLevel, String partnerOpenId) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<String, Object>();

		if (searchParams != null) {
			Set<String> keys = searchParams.keySet();
			for (String key : keys) {
				Object value = searchParams.get(key);
				if (value != null) {
					if ("vipLevel".equals(key)) {
						String _value = (String) value;
						Integer _vipLevel = Integer.valueOf(_value);
						sql.append(" AND bean.vipLevel =:vipLevel ");
						parameters.put("vipLevel", _vipLevel);
					} else {
						sql.append(" AND bean." + key + " LIKE :" + key + " ");
						parameters.put(key, "%" + value + "%");
					}
				}
			}
		}
		Date _startTime = null;
		if (startTime != null) {
			String startTimeStr = DateUtils.getDateStr(startTime, "yyyy-MM-dd") + " 00:00:00";
			_startTime = DateUtils.getDateFromDateStr(startTimeStr, "yyyy-MM-dd HH:mm:ss");

		}
		Date _endTime = null;
		if (endTime != null) {
			String endTimeStr = DateUtils.getDateStr(endTime, "yyyy-MM-dd") + " 23:59:59";
			_endTime = DateUtils.getDateFromDateStr(endTimeStr, "yyyy-MM-dd HH:mm:ss");
		}

		if (_startTime != null) {
			sql.append(" AND bean.registerTime >=:startTime ");
			parameters.put("startTime", _startTime);
		}
		if (_endTime != null) {
			sql.append(" AND bean.registerTime <=:endTime");
			parameters.put("endTime", _endTime);
		}

		if (null != vipLevel) {
			sql.append(" AND bean.vipLevel =:vipLevel");
			parameters.put("vipLevel", vipLevel);
		}

		if (StrUtils.isNotNULL(partnerOpenId)) {
			sql.append(" AND bean.partnerOpenId =:partnerOpenId");
			parameters.put("partnerOpenId", partnerOpenId);
		}

		if (StrUtils.isNotNULL(sortParam) && StrUtils.isNotNULL(sortType)) {
			sql.append(" ORDER BY " + sortParam + " " + sortType);
		}

		return super.queryForPage(Member.class, sql.toString(), parameters, pageNo, pageSize);
	}

	@Override
	public Member findMemberByCardNo(String cardNo) {
		StringBuilder sql = new StringBuilder("FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.cardNo = :cardNo ");
		parameters.put("cardNo", cardNo);

		List<Member> result = super.query(Member.class, sql.toString(), parameters);
		return result.isEmpty() ? null : result.get(0);
	}

	@Override
	public List<Member> findMembersForRank(int limitCounts) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		sql.append(" ORDER BY bean.fansCounts DESC");

		return super.queryForLimit(Member.class, sql.toString(), parameters, limitCounts);
	}

	@Override
	public List<Member> findMembersPage(Integer pageNo, Integer pageSize) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		return queryForPageList(Member.class, sql.toString(), parameters, pageNo, pageSize);
	}

	@Override
	public Long findPartnerCounts() {
		StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		// sql.append(" AND bean.vipLevel = :vipLevel ");
		// parameters.put("vipLevel", Member.VIP_LEVEL_PARTNER);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		List<Long> result = super.query(Long.class, sql.toString(), parameters);
		return result.isEmpty() ? 0L : result.get(0);
	}

	@Override
	public List<Member> findNoPartnerAgentMembers(int limitCounts) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.vipLevel = :vipLevel ");
		parameters.put("vipLevel", Member.VIP_LEVEL_HIGHT);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		List<Member> result = super.queryForLimit(Member.class, sql.toString(), parameters, limitCounts);
		List<Member> _result = new ArrayList<Member>();
		for (Member member : result) {
			if (StrUtils.isNULL(member.getPartnerCardNo()) && StrUtils.isNULL(member.getPartnerOpenId())) {
				_result.add(member);
			}
		}
		return _result;
	}

	@Override
	public List<Member> findPartnerAgentPage(Integer pageNo, Integer pageSize, String partnerOpenId) {
		StringBuilder sql = new StringBuilder("FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.partnerOpenId = :partnerOpenId ");
		parameters.put("partnerOpenId", partnerOpenId);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		sql.append(" ORDER BY bean.fansCounts DESC");

		List<Member> result = queryForPageList(Member.class, sql.toString(), parameters, pageNo, pageSize);

		return result;
	}

	@Override
	public Member findByMobile(String mobile) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.mobile = :mobile ");
		parameters.put("mobile", mobile);

		List<Member> result = super.query(Member.class, sql.toString(), parameters);
		return result.isEmpty() ? null : result.get(0);
	}

	@Override
	public List<Member> findFans(String chiefOpenId) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.chiefOpenId = :chiefOpenId ");
		parameters.put("chiefOpenId", chiefOpenId);

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		return super.query(Member.class, sql.toString(), parameters);
	}

	@Override
	public List<Member> findMembersPage(Integer pageNo, Integer pageSize, List<Integer> levelList) {
		StringBuilder sql = new StringBuilder(" FROM Member bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.status = :status ");
		parameters.put("status", Member.STATUS_USE);

		sql.append(" AND bean.followStatus = :followStatus ");
		parameters.put("followStatus", Member.FOLLOW_STATUS_YES);

		StringBuilder levels = new StringBuilder();
		if (null != levelList) {
			if (!levelList.isEmpty()) {
				
				for (Integer level : levelList) {
					levels.append("'" + level + "',");
				}
			}
		}
		sql.append(" AND bean.vipLevel IN (" + levels.substring(0, levels.length() - 1) + ") ");

		return queryForPageList(Member.class, sql.toString(), parameters, pageNo, pageSize);
	}

}
